package doc2db.fileWorker.xml;

import java.util.ArrayList;
import java.util.List;

/**
 * Класс узел, который может содержать свои дочернеи узлы
 * (дерево, или ветвь дерева, которая может разветвлятся
 * и иметь свои листья)
 *<pre>
 *                   ┌──────────────┐
 *                   │text="null"   │
 *                   │list.size=3   │
 *                   │father=NULL   │
 *                   │degreeInward=0│
 *                   └──────┬───────┘
 *                   /      │       \
 *                  /       │        \
 * ┌──────────────┐/ ┌──────┴───────┐ \┌──────────────┐
 * │text="...1"   │  │text="...2"   │  │text="...3"   │
 * │list.size=... │  │list.size=... │  │list.size=... │
 * │father="null" │  │father="null" │  │father="null" │
 * │degreeInward=1│  │degreeInward=1│  │degreeInward=1│
 * └──────────────┘  └──────────────┘  └──────────────┘
 *     /    \            /    \           /      \
 *    /  ... \          /  ... \         /        \
 *  ...      ...      ...      ...      /    ...   \
 *                              ┌───────┴──────┐   ...
 *                              │text="...3_1" │
 *                              │list.size=null│
 *                              │father="...3" │
 *                              │degreeInward=2│
 *                              └──────────────┘
 *</pre>
 * @author yura
 */
public class TreeTypeNodes {
    /**
     * текст данной ветви , НОЛЬ если
     * это прорадительская ветвь
     */
    private String text = "null";
    /**
     * ветви данной ветви , или НОЛЬ в случае ,
     * если детей нет , тоесть это "лист"
     */
    private List<TreeTypeNodes> list = null;
    /**
     * прорадительская ветвь , или НОЛЬ в случае ,
     * если это прорадительская ветвь
     */
    private TreeTypeNodes father = null;
    /**
     * степень вложености , 0 - первая ветвь
     */
    private int degreeInward = 0;
    /**
     * Является ли данноя консрукция не актуальеой, уже
     */
    private boolean existsAlready = false;

    /**
     * Создаёт пустой узел
     * @param text текст в узле
     */
    public TreeTypeNodes(String text){
        this.text = text;
    }

    /**
     * Создаёт пустой узел
     * @param text текст в узле
     * @param degree степень вложености
     */
    public TreeTypeNodes(String text, int degree){
        this(text);
        this.degreeInward = degree;
    }

    /**
     * Создаёт пустой узел
     * @param text текст в узле
     * @param father родительский элемент
     */
    public TreeTypeNodes(String text, TreeTypeNodes father){
        this.text = text;
        this.father = father;
    }

    /**
     * Создаёт пустой узел
     * @param text текст в узле
     * @param father родительский элемент
     * @param degree степень вложености
     */
    public TreeTypeNodes(String text, TreeTypeNodes father, int degree){
        this(text, father);
        this.degreeInward = degree;
    }

    /**
     * Создаёт информативный узел
     * @param text текст в узле
     * @param list список дочерних узлов
     */
    public TreeTypeNodes(String text, List<TreeTypeNodes> list) {
        this.text = text;
        this.list = list;
    }

    /**
     * Создаёт информативный узел
     * @param text текст в узле
     * @param list список дочерних узлов
     * @param degree степень вложености
     */
    public TreeTypeNodes(String text, List<TreeTypeNodes> list, int degree) {
        this(text, list);
        this.degreeInward = degree;
    }

    /**
     * Создаёт информативный узел
     * @param text текст в узле
     * @param list список дочерних узлов
     * @param father родительский элемент
     */
    public TreeTypeNodes(String text, List<TreeTypeNodes> list, TreeTypeNodes father) {
        this.text = text;
        this.list = list;
        this.father = father;
    }

    /**
     * Создаёт информативный узел
     * @param text текст в узле
     * @param list список дочерних узлов
     * @param father родительский элемент
     * @param degree степень вложености
     */
    public TreeTypeNodes(String text, List<TreeTypeNodes> list, TreeTypeNodes father, int degree) {
        this(text, list, father);
        this.degreeInward = degree;
    }

    private TreeTypeNodes(TreeTypeNodes node) {
        this(node.getText(), node.getList(), node.getFather(), node.getDegreeInward());
    }

    /**
     * Добовляет дочерний пустой узел к данному узлу
     * @param text текст дочернего узла
     * @return добавнлен ли узел, или нет
     */
    public boolean addNodeInList(String text){
        if(list == null)
            list = new ArrayList<TreeTypeNodes>();
        return list.add(new TreeTypeNodes(text));
    }

    /**
     * Добовляет дочерний пустой узел к данному узлу
     * @param text текст дочернего узла
     * @param father родительский элемент
     * @return добавнлен ли узел, или нет
     */
    public boolean addNodeInList(String text, TreeTypeNodes father){
        if(list == null)
            list = new ArrayList<TreeTypeNodes>();
        return list.add(new TreeTypeNodes(text, father));
    }

    /**
     * Добовляет дочерний пустой узел к данному узлу
     * @param text текст дочернего узла
     * @param father родительский элемент
     * @param degree степень вложености
     * @return добавнлен ли узел, или нет
     */
    public boolean addNodeInList(String text, TreeTypeNodes father, int degree){
        if(list == null)
            list = new ArrayList<TreeTypeNodes>();
        return list.add(new TreeTypeNodes(text, father, degree));
    }

    /**
     * Добовляет дочерний узел, со своими дочерними узлами,
     * к данному узлу
     * @param text текст дочернего узла
     * @param list список дочерних узлов добовляемого дочернего узла
     * @return добавнлен ли узел, или нет
     */
    public boolean addNodeInList(String text, List<TreeTypeNodes> list){
        if(list == null)
            list = new ArrayList<TreeTypeNodes>();
        return list.add(new TreeTypeNodes(text, list));
    }

    /**
     * Добовляет дочерний узел, со своими дочерними узлами,
     * к данному узлу
     * @param text текст дочернего узла
     * @param list список дочерних узлов добовляемого дочернего узла
     * @param father родительский элемент
     * @return добавнлен ли узел, или нет
     */
    public boolean addNodeInList(String text, List<TreeTypeNodes> list, TreeTypeNodes father){
        if(list == null)
            list = new ArrayList<TreeTypeNodes>();
        return list.add(new TreeTypeNodes(text, list, father));
    }

    public boolean addNodeInList(TreeTypeNodes node){
        if(list == null)
            list = new ArrayList<TreeTypeNodes>();
        return list.add(new TreeTypeNodes(node));
    }



    /**
     * Является ли данный узел последним в дереве, тоесть
     * есть ли у него свои дочернии узлы. Если у данного узла
     * нет своих дочерних узлов - значит он последний
     * @return true/false
     */
    public boolean isLastElem(){
        if(list == null)
            return true;
        else
            return false;
    }

    /**
     * Является ли данный узел первым в дереве, тоесть
     * нет ли у него прорадителей. Если у данного узла
     * нет прорадителей - значит он корневой
     * @return true/false
     */
    public boolean isFatherElem(){
        if(father == null)
            return true;
        else
            return false;
    }

    /**
     * Возвращяет список дочерних узлов
     * @return
     */
    public List<TreeTypeNodes> getList() {
        return list;
    }

    /**
     * Внести список дочерних узлов целиком
     * @param list список узлов
     */
    public void setList(List<TreeTypeNodes> list) {
        this.list = list;
    }

    /**
     * Указывает количество дочерних узлов, если дочерних узлов
     * нет, то будет указан 0
     * @return количество дочерних узлов
     */
    public int getListSize(){
        if(list != null)
            return list.size();
        else
            return 0;
    }

    /**
     * Выдаёт указанный дочерний узел.
     * Если дочерних узлов нет, то будет выданно значение "null".
     * Если индекс указан не правильно, то будет выданно значение "null".
     * @param index индекс дочерних узла
     * @return дочерний узлел
     */
    public TreeTypeNodes getElemInList(int index){
        if(list == null)
            return null;
        if(index >= 0 && index < list.size())
            return list.get(index);
        else
            return null;
    }

    /**
     * Removes the element at the specified position in this list
     * (optional operation). Shifts any subsequent elements to the
     * left (subtracts one from their indices). Returns the element
     * that was removed from the list.
     * @param index the index of the element to be removed
     * @return the element previously at the specified position
     */
    public TreeTypeNodes removeElemInList(int index){
        if(list == null)
            return null;
        if(index >= 0 && index < list.size())
            return list.remove(index);
        else
            return null;
    }

    /**
     * Removes the first occurrence of the specified element from
     * this list, if it is present (optional operation). If this
     * list does not contain the element, it is unchanged. More
     * formally, removes the element with the lowest index i such
     * that (o==null ? get(i)==null : o.equals(get(i))) (if such
     * an element exists). Returns true if this list contained the
     * specified element (or equivalently, if this list changed as
     * a result of the call).
     * @param object element to be removed from this list, if present
     * @return  true if this list contained the specified element
     */
    public boolean removeElemInList(TreeTypeNodes object){
        if(list == null)
            return false;
        else
            return list.remove(object);
    }



    /**
     * Выдаёт текст данного узла
     * @return текст данного узла
     */
    public String getText() {
        return text;
    }

    /**
     * Внести текст данного узла
     * @param text
     */
    public void setText(String text) {
        this.text = text;
    }


    /**
     * Установить радительский элемент
     * @param father радительский элемент
     */
    public void setFather(TreeTypeNodes father){
        this.father = father;
    }

    /**
     *  Радительский элемент
     * @return радительский элемент
     */
    public TreeTypeNodes getFather(){
        return father;
    }


    /**
     * степень вложености , 0 - первая ветвь
     * @return степень вложености
     */
    public int getDegreeInward() {
        return degreeInward;
    }

    /**
     * степень вложености , 0 - первая ветвь
     * @param degreeInward степень вложености
     */
    public void setDegreeInward(int degreeInward) {
        this.degreeInward = degreeInward;
    }

    /**
     * Является ли данноя консрукция не актуальеой, уже
     * @return true если да - не актуальнф и false в обратном
     */
    public boolean isExistsAlready() {
        return existsAlready;
    }

    /**
     *   Установить является ли данноя консрукция
     * не актуальеой, уже
     * @param existsAlready true если да - не актуальнф
     * и false в обратном
     */
    public void setExistsAlready(boolean existsAlready) {
        this.existsAlready = existsAlready;
    }


    
}
